package com.scalar.chiptrack.jasper.base;

import com.scalar.chiptrack.ChipTrackAction;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.chiptrack.jasper.base.datasource.ChiptrackJasperDataSource;
import com.scalar.chiptrack.commons.SessionKeys;
import com.scalar.chiptrack.commons.Constants;
import com.scalar.chiptrack.users.User;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;

import net.sf.jasperreports.engine.*;

/**
 *
 */
public abstract class AbstractJasperReportsAction extends ChipTrackAction {
	@Override
	public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
		HttpSession pSession = null;
        User pUser = null;
        // Assign current session
        pSession = httpServletRequest.getSession();

        // Get current user
        pUser = (User) pSession.getAttribute(SessionKeys.USER_KEY);

        // Redirect the user to login page, if he/she is not logged in
        if (pUser == null) {
            //todo need to forward to login page or simply return a message saying not loggedin based on the request type.
            pSession.setAttribute(SessionKeys.SOURCE_PAGE_KEY, httpServletRequest.getServletPath() + "?" + httpServletRequest.getQueryString());
            return (actionMapping.findForward(SessionKeys.ACTION_FORWARD_KEY_LOGIN));
        }
        // Create and add Errors HashMap to the request
        httpServletRequest.setAttribute(SessionKeys.ERROR_MESSAGES, new HashMap());
        // Create and add Info Messages HashMap to the request
        httpServletRequest.setAttribute(SessionKeys.INFO_MESSAGES, new HashMap());

		JasperPrint jasperPrint = null;
		if("true".equalsIgnoreCase(httpServletRequest.getParameter(Constants.REQUEST_PARAM_USE_CACHE))) {
			jasperPrint = (JasperPrint)httpServletRequest.getSession().getAttribute(JasperReportsHelper.getJasperPrintSessionParamName(httpServletRequest, null));
		}
		if(jasperPrint == null) {
			Map paramMap = JasperReportsHelper.getParamMap(httpServletRequest);

			//set any additional report specific params
			setReportParams(paramMap, httpServletRequest);

			ChiptrackJasperDataSource chiptrackJasperDataSource = getJasperDataSource(paramMap, httpServletRequest);
			Boolean isIgnorePagination = (Boolean)paramMap.get(JRParameter.IS_IGNORE_PAGINATION);

			paramMap.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.TRUE);
			jasperPrint = getJasperPrint(chiptrackJasperDataSource, httpServletRequest, JasperReportsHelper.getJasperReport(httpServletRequest), paramMap);
			httpServletRequest.getSession().setAttribute(JasperReportsHelper.getJasperPrintSessionParamName(httpServletRequest, true), jasperPrint);

			paramMap.put(JRParameter.IS_IGNORE_PAGINATION, Boolean.FALSE);
			chiptrackJasperDataSource.moveFirst();
			jasperPrint = getJasperPrint(chiptrackJasperDataSource, httpServletRequest, JasperReportsHelper.getJasperReport(httpServletRequest), paramMap);
			httpServletRequest.getSession().setAttribute(JasperReportsHelper.getJasperPrintSessionParamName(httpServletRequest, false), jasperPrint);

			//back to original value
			paramMap.put(JRParameter.IS_IGNORE_PAGINATION, isIgnorePagination);
		}

		//Build uri for PDF and EXCEL
		String reportURI = httpServletRequest.getRequestURI();
		StringBuffer paramStr = new StringBuffer();
		Map paramMap = httpServletRequest.getParameterMap();
		Iterator itr = paramMap.keySet().iterator();
		while(itr.hasNext()) {
			String key = (String)itr.next();
			if(!Constants.REQUEST_PARAM_REPORT_TYPE.equals(key) && !Constants.REQUEST_PARAM_PAGE.equals(key)
					&& !Constants.REQUEST_PARAM_USE_CACHE.equals(key) && !Constants.REQUEST_PARAM_IGNORE_PAGINATION.equals(key)
					) {
				paramStr.append("&").append(key).append("=").append(((String[])paramMap.get(key))[0]);
			}
		}
		String referer = httpServletRequest.getParameter(Constants.REQUEST_PARAM_REFERER);
		if(StringUtils.isNullOrEmpty(referer)) {
			referer = httpServletRequest.getHeader(Constants.REQUEST_PARAM_REFERER);
			paramStr.append("&").append(Constants.REQUEST_PARAM_REFERER).append("=").append(referer);
		}
		String pdfURI = reportURI + "?" + Constants.REQUEST_PARAM_REPORT_TYPE + "=" + Constants.REPORT_TYPE_PDF + "&" + Constants.REQUEST_PARAM_USE_CACHE + "=true" + paramStr;
		String excelURI = reportURI + "?" + Constants.REQUEST_PARAM_REPORT_TYPE + "=" + Constants.REPORT_TYPE_EXCEL + "&" + Constants.REQUEST_PARAM_USE_CACHE + "=true" + "&" + Constants.REQUEST_PARAM_IGNORE_PAGINATION + "=true" + paramStr;
		String htmlURI = reportURI + "?" + Constants.REQUEST_PARAM_REPORT_TYPE + "=" + Constants.REPORT_TYPE_HTML  + paramStr;

		httpServletRequest.setAttribute(Constants.REQUEST_PARAM_PDF_URI, pdfURI);
		httpServletRequest.setAttribute(Constants.REQUEST_PARAM_EXCEL_URI, excelURI);
		httpServletRequest.setAttribute(Constants.REQUEST_PARAM_HTML_URI, htmlURI);
		httpServletRequest.setAttribute(Constants.REQUEST_PARAM_REFERER, referer);

		return JasperReportsHelper.exportReport(jasperPrint, actionMapping, httpServletRequest, httpServletResponse);
	}

	public JasperPrint getJasperPrint(ChiptrackJasperDataSource dataSource, HttpServletRequest httpServletRequest, JasperReport jasperReport, Map paramMap) throws Exception {
		return JasperFillManager.fillReport(jasperReport, paramMap, dataSource);
	}

	public abstract ChiptrackJasperDataSource getJasperDataSource(Map paramMap, HttpServletRequest request) throws Exception;

	/**
	 * Override this method to set the report specific params if any.<br>
	 * Add the additional params required in the <code>paramMap</code>.
	 *
	 * @param paramMap parameter map to be passed to the report
	 * @param request <code>HttpServletRequest</code>
	 */
	public void setReportParams(Map paramMap, HttpServletRequest request) {
		//override if necessary
	}
}
